#region Using directives

using System;
using System.Collections.Generic;
using System.Text;

using Weazel.Math;
using Weazel.Gezel.Simulator.Reference.Profiling;

#endregion

namespace Weazel.Gezel.Simulator.Reference
{
	class AssignSignal : AbstractSignal
	{
        private Profiler profiler;
		private AbstractSignal left;
		private AbstractSignal right;

		/// <summary>
		/// Caches the assigned value
		/// </summary>
		private Integer value;

		public AssignSignal(Symid id, Symid context, AbstractSignal left, AbstractSignal right, Simulation sim)
			: base(id, null)
		{
			this.left = left;
			this.right = right;

			this.left.newDefiner(context, this);
			value = new Integer((int)right.Width(), right.Signed() == 1);

            if (sim.profiler != null)
            {
                profiler = sim.profiler;
                profiler.MakeOperation(this, value.Width);
            }
		}

    internal override Integer Evaluate(AbstractIpBlock ip, long targetGeneration)
		{
			try
			{
				Integer temp = right.Evaluate(ip, targetGeneration);
				value.ValueCopy(temp);
				left.Assign(value);

                if (profiler != null)
                    profiler.EvaluateOperation(Id, value);

				return value;
			}
			catch (IndexOutOfRangeException)
			{
				throw new ExpressionEvaluationException(string.Format("could not assign to entity '{0}' due to invalid index in expression", left.Name));
			}
		}

		public override bool TraceToSignal(Symid toSignalId, List<AbstractSignal> signals)
		{
			return right.TraceToSignal(toSignalId, signals);
		}
	}
}